package com.gzhryc.shared_device.oem.micro.api.controllers.xcx.v1.cdcz;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.api.DefaultAPIResponse;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.servlet.DtoConstants;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.cdcz.code.CDCZCostConfig;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZFeeTemplate;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrder;
import com.gzhryc.shared_device.cdcz.code.dao.db.ChargeSocket;
import com.gzhryc.shared_device.cdcz.code.dao.db.ChargeSocketSlot;
import com.gzhryc.shared_device.cdcz.code.dao.enums.CDCZOrderEnum;
import com.gzhryc.shared_device.cdcz.code.dao.enums.ChargeSocketEnum;
import com.gzhryc.shared_device.cdcz.code.dao.enums.ChargeSocketSlotEnum;
import com.gzhryc.shared_device.cdcz.code.dao.models.CDCZPowerIntervalMoneyContent;
import com.gzhryc.shared_device.cdcz.code.services.CDCZFeeTemplateService;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderService;
import com.gzhryc.shared_device.cdcz.code.services.ChargeSocketService;
import com.gzhryc.shared_device.cdcz.code.services.ChargeSocketSlotService;
import com.gzhryc.shared_device.cdcz.core.ICDCZNetworkService;
import com.gzhryc.shared_device.cdcz.core.models.CDCZExecuteResult;
import com.gzhryc.shared_device.common.device.dao.db.Device;
import com.gzhryc.shared_device.common.device.services.DeviceService;
import com.gzhryc.shared_device.oem.code.ConfigUtils;
import com.gzhryc.shared_device.oem.code.HttpNetworkServiceUtils;
import com.gzhryc.shared_device.oem.code.device.EDeviceFunCode;
import com.gzhryc.shared_device.oem.code.member.LoginMember;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberBusinessOrder;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberWallet;
import com.gzhryc.shared_device.oem.code.member.dao.enums.MemberBusinessOrderEnum;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.member.services.MemberWalletService;
import com.gzhryc.shared_device.oem.code.member.services.dto.MemberBusinessOrderSearch;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceBusinessConfig;
import com.gzhryc.shared_device.oem.code.place.services.PlaceBusinessConfigService;
import com.gzhryc.shared_device.oem.micro.api.MicroConstants;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.ClientAPICodeConstants;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.cdcz.CDCZOrderCloseRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.cdcz.CDCZOrderWorkingRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.cdcz.CDCZOrderWorkingResponse;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.cdcz.CDCZScanGetRequest;
import com.gzhryc.shared_device.oem.micro.api.dto.xcx.v1.cdcz.CDCZScanGetResponse;

/**
 * 充电插座扫码服务控制器
 * @version 2022-09-27
 */
public class CDCZScanController {

    static Logger log = Logger.getLogger(CDCZScanController.class);

    @Route(value = { "/xcx/v1/cdcz/scan/get.do" }, method = "POST")
    public CDCZScanGetResponse getSharedDevice(HttpServletRequest request) {
        CDCZScanGetResponse apiResp = new CDCZScanGetResponse(ClientAPICodeConstants.NULL_DATA, "未找到设备信息");
        CDCZScanGetRequest apiReq = WebUtils.getJsonRequest(request, CDCZScanGetRequest.class);
        if (apiReq != null && StringUtils.isNotBlank(apiReq.getBody().getDeviceSn())) {
            String deviceSn = apiReq.getBody().getDeviceSn().trim();
            LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);
            Device device = DeviceService.self().getByDeviceSn(deviceSn);
            if (device == null || device.getPlaceId() == null) {
                log.error("未找到{{0}}设备或未部署",deviceSn);
                return apiResp;
            }

            ChargeSocket chargeSocket = ChargeSocketService.self().getByDeviceSn(deviceSn);
            if (chargeSocket == null) {
                log.error("未找到{{0}}设备",deviceSn);
                return apiResp;
            }

            apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
            apiResp.getBody().setDeviceSn(device.getDeviceSn());
            if(ChargeSocketEnum.State.Online.index().equals(chargeSocket.getState())){
                //TODO 检查充电饱和状态
                apiResp.getBody().setState(1);  //在线
            }else{
                apiResp.getBody().setState(2);  //离线
                return apiResp;
            }

            if(apiReq.getBody().getSlotNum() != null){
                ChargeSocketSlot deviceSlot = ChargeSocketSlotService.self().getByKeys(device.getDeviceSn(),apiReq.getBody().getSlotNum());
                if(deviceSlot == null){
                    log.error("未找到{{0}}设备的{{1}}号卡槽", deviceSn,apiReq.getBody().getSlotNum());
                    apiResp.setMsg("未找到" + apiReq.getBody().getSlotNum() + "号插座");
                    return apiResp;
                }

                if(ChargeSocketSlotEnum.State.Working.index().equals(deviceSlot.getState())){
                    apiResp.setMsg(apiReq.getBody().getSlotNum() + "号插座正在工作");
                    return apiResp;
                }
            }else {
                apiResp.getBody().setSlotList(new ArrayList<>());
                List<ChargeSocketSlot> socketSlotList = ChargeSocketSlotService.self().findByDeviceSn(device.getDeviceSn());
                if (socketSlotList == null) {
                    socketSlotList = new ArrayList<>();
                }
                for (int i = 1; i <= chargeSocket.getSlotTotal(); i++) {
                    CDCZScanGetResponse.SlotItem item = new CDCZScanGetResponse.SlotItem();
                    item.setSlotNum(i);
                    for (ChargeSocketSlot slot : socketSlotList) {
                        if (item.getSlotNum().equals(slot.getSlotNum())) {
                            item.setState(slot.getState());
                            break;
                        }
                    }
                    apiResp.getBody().getSlotList().add(item);
                }
            }

            //获取用户钱包
            MemberWallet wallet = MemberWalletService.self().getByMemberId(member.getId());

            CDCZFeeTemplate feeTemplate = null;
            PlaceBusinessConfig deviceFunc = PlaceBusinessConfigService.self().getByKeys(device.getPlaceId(), EDeviceFunCode.CDCZ.index());
            if(deviceFunc != null && deviceFunc.getFeeTemplateId() != null) {
                feeTemplate = CDCZFeeTemplateService.self().getById(deviceFunc.getFeeTemplateId());
            }

            if(feeTemplate == null){
                CDCZCostConfig costConfig = ConfigUtils.getCDCZCostConfig();
                feeTemplate = CDCZFeeTemplateService.buildByDefault(costConfig);
            }

            apiResp.getBody().setElectricityMeterCost(new CDCZScanGetResponse.ElectricityMeterCost());
            apiResp.getBody().getElectricityMeterCost().setMinDepositMoney(feeTemplate.getMinWalletMoneyStr());
            apiResp.getBody().getElectricityMeterCost().setMaxChargeTimesMinute(feeTemplate.getMaxChargeTimesMinute());
            apiResp.getBody().getElectricityMeterCost().setMaxChargeElectricity(feeTemplate.getMaxChargeElectricity());
            if(wallet != null && wallet.getMoney() >= feeTemplate.getMinWalletMoney()){
                apiResp.getBody().getElectricityMeterCost().setWalletState(1);
            }else{
                apiResp.getBody().getElectricityMeterCost().setWalletState(2);
            }

            if(StringTools.isNotBlank(feeTemplate.getTimeSetMeal())) {
                String[] timeSetMeal = feeTemplate.getTimeSetMeal().split(",");
                apiResp.getBody().setTimeSetMealList(Arrays.asList(timeSetMeal));
            }

            String pimContentJson = feeTemplate.getPimContent();
            if(StringTools.isNotBlank(pimContentJson)) {
                CDCZPowerIntervalMoneyContent pimContent = JsonTools.fromJson(pimContentJson, CDCZPowerIntervalMoneyContent.class);
                if (pimContent != null && pimContent.getItems().size() > 0){
                    apiResp.getBody().setPimItems(new ArrayList<>());
                    for(CDCZPowerIntervalMoneyContent.Item item : pimContent.getItems()){
                        CDCZScanGetResponse.PimItem pimItem = new CDCZScanGetResponse.PimItem();
                        pimItem.setMinPower(item.getMinPower());
                        pimItem.setMaxPower(item.getMaxPower());
                        pimItem.setMoneyStr(item.getMoneyStr());
                        apiResp.getBody().getPimItems().add(pimItem);
                    }
                }
            }
        }
        return apiResp;
    }

    @Route(value = { "/xcx/v1/cdcz/order/close.do" }, method = "POST")
    public DefaultAPIResponse orderClose(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "关闭设备失败");
        CDCZOrderCloseRequest apiReq = WebUtils.getJsonRequest(request, CDCZOrderCloseRequest.class);
        if (apiReq != null && StringUtils.isNotBlank(apiReq.getBody().getTradeNo())) {
            CDCZOrder order = CDCZOrderService.self(new Date()).getByTradeNo(apiReq.getBody().getTradeNo());
            if (order == null) {
                apiResp.setMsg("未找到订单信息");
                return apiResp;
            }

            if(!CDCZOrderEnum.State.Working.index().equals(order.getState())){
                apiResp.setMsg("当前状态无法关闭");
                return apiResp;
            }

            ChargeSocket chargeSocket = ChargeSocketService.self().getByDeviceSn(order.getChargeSocketSn());
            if (chargeSocket != null) {
                ICDCZNetworkService networkService = HttpNetworkServiceUtils.getCDCZNetworkService(chargeSocket.getIotNodeId());
                if (networkService != null) {
                    CDCZExecuteResult executeResult = networkService.closeCharge(order.getChargeSocketSn(), order.getSlotNum());
                    if (executeResult != null) {
                        if (CDCZExecuteResult.SUCCESS.equals(executeResult.getCode())) {
                            apiResp.setCode(DtoConstants.SUCCESS, null);
                        } else if (StringTools.isNotBlank(executeResult.getMsg())) {
                            apiResp.setMsg(executeResult.getMsg());
                        } else {
                            apiResp.setMsg("通信失败,请稍后再试");
                        }
                    } else {
                        apiResp.setMsg("充电插座网络服务无响应");
                    }
                } else {
                    apiResp.setMsg("未获取充电插座网络服务");
                }
            } else {
                apiResp.setMsg("未找到设备信息");
            }
        }
        return apiResp;
    }

    @Route(value = { "/xcx/v1/cdcz/order/working/get.do" }, method = "POST")
    public CDCZOrderWorkingResponse getWorkingOrder(HttpServletRequest request){
        CDCZOrderWorkingResponse apiResp = new CDCZOrderWorkingResponse(ClientAPICodeConstants.NULL_DATA, "未找到订单信息");
        CDCZOrderWorkingRequest apiReq = WebUtils.getJsonRequest(request, CDCZOrderWorkingRequest.class);
        if (apiReq != null && StringUtils.isNotBlank(apiReq.getBody().getDeviceSn())) {
            LoginMember member = WebUtils.getAttribute(request, MicroConstants.ATTR_LOGIN_MEMBER, LoginMember.class);

            MemberBusinessOrderSearch search = new MemberBusinessOrderSearch();
            search.setDeviceSn(apiReq.getBody().getDeviceSn());
            search.setMemberId(member.getId());
            search.setState(MemberBusinessOrderEnum.State.Working.index());
            //TODO 查询范围-当年
            Date currentDate = new Date();
            MemberBusinessOrder businessOrder = MemberBusinessOrderService.self(currentDate).getBySearch(search);
            if(businessOrder != null && EDeviceFunCode.CDCZ.index().equals(businessOrder.getDeviceFunCode())){
                CDCZOrder order = CDCZOrderService.self(new Date()).getByTradeNo(businessOrder.getTradeNo());
                if(order != null){
                    apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                    apiResp.getBody().setTradeNo(order.getTradeNo());
                    apiResp.getBody().setCostMode(order.getCostMode());
                    apiResp.getBody().setCostModeName(order.getCostModeName());
                    apiResp.getBody().setMoney(order.getMoneyStr());
                    apiResp.getBody().setCreateDate(order.getCreateDate());
                }
            }
        }
        return apiResp;
    }
}
